package org.jeecg.modules.simulator.rooter;

import lombok.Getter;
import lombok.Setter;

import org.jeecg.modules.simulator.Simulator;

import org.jeecg.modules.simulator.factory.person.GodAssistanter;
import org.jeecg.modules.simulator.factory.person.RouteObjecter;
import org.jeecg.modules.simulator.jsonot.*;

import org.jeecg.modules.simulator.model.SceneDataType;
import org.jeecg.modules.simulator.model.SceneParam;
import org.jeecg.modules.simulator.model.line.Line;

import org.jeecg.modules.simulator.model.line.station.station.Station;
import org.jeecg.modules.simulator.model.line.station.station.TransferStation;
import org.jeecg.modules.simulator.model.person.Person;

import org.jeecg.modules.simulator.service.HistoryBizPersonLoaderService;
import org.jeecg.modules.simulator.util.TimeUtil;
import org.jeecg.modules.simulator.util.UnitCache;
import org.springframework.data.redis.core.RedisTemplate;
import org.jeecg.modules.simulator.factory.person.PersonsCreater;


import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

//造人程序
public class God implements Simulator {
   private final int strPosition = 4;// 要插入站点下划线的位置
private final  int strLinePosition = 2;
    @Setter
    String sceneCode;


    StationChecker stationChecker = new StationChecker();
//    @Getter
//    RouteObjecter routeObjecter = new RouteObjecter();
    @Setter
    @Getter
    GodAssistanter godAssistanter;
    @Getter
    @Setter
    Map<String, TransferStation> transferStationMap;

    @Setter
    //总station集合，使用的是stationId,做key
    Map<String, Station> stationMap = new HashMap<>();
    //    @Setter
//    Map<String, Station> stationAllMap = new HashMap<>();
//    @Setter
//    //stationName,使用站名做Key
//    Map<String, Station> stationNameMap = new HashMap<>();

    @Getter
    //按线路Id做的LineRooter
    Map<String, LineRooter> lineRooterMap = new HashMap<>();

    List<String> lines = new ArrayList<>();
    public void setLineRooterMap(Map<String, LineRooter> lineRooterMap) {
        this.lineRooterMap = lineRooterMap;

        for (LineRooter lineRooter : lineRooterMap.values()) {
            Line line = lineRooter.getLine();
            if (line != null) {
                lines.add(line.getLineId());
            }
        }



    }


    @Setter
    HistoryBizPersonLoaderService historyBizPersonLoaderService;


//    private final String pattern = "Simu_*";
//
//    private final String prefixRouteName = "Simu_";


    @Getter
    @Setter
    private RedisTemplate<String, Object> redisTemplate;
    //    @Getter
//    @Setter
//    //key是o点站点ID-D点站点ID，value是路径概率信息，同一个od可能会有多条路径
//    Map<String, List<ODProbabilityApiInfo>> odProbabilityApiInfosMap = new HashMap<>();
    @Getter
    @Setter
    Map<String, List<ODProbabilityApiInfo>> odProbabilityApiInfoMap = new HashMap<>();


    @Getter
    @Setter
    Map<String, Map<String, NumPeopEnStationApiInfo>>   numPeopEnStationApiInfoMap= new HashMap<>();
//
//
//    @Getter
//    @Setter
//    //原始的路径概率有可能因为过滤的情况，在路径表中找不到对应的路径，所以需要过滤
//    Map<String, List<ODProbabilityApiInfo>> odProbabilityApiInfosFilterMap = new HashMap<>();


    PersonsCreater personsCreater=new PersonsCreater();

//分配人数给每个站
    public void assignPerson2station(String now) {



        for(LineRooter lineRooter:lineRooterMap.values()){
            Line line = lineRooter.getLine();
            Map<String, Station> lineStationMap = line.getStationMap();
            calcullatePerson2Station(now, lineStationMap);
        }

    }


//5分钟后每个站点预计要出现的实时进站人数
    public Map<String, NumPeopEnStationApiInfo> getAfter5MinutePersonNums(String now) {
        LocalTime localTime1 = TimeUtil.transTimeString2LocalTime(now);
        LocalTime updatedTime = localTime1.plusMinutes(5);
        String fiveAfterTimeStr=TimeUtil.Lcaltime2String(updatedTime);
        return  numPeopEnStationApiInfoMap.get(fiveAfterTimeStr);

}




/** 
* @description:
*
 * 1、检查进站的是否有外来新增人数
 * 2、加载历史数据给站点
* @author: renzhg
* @date: 2025/2/6 16:29
**/
private void processStationData(String now, Map.Entry<String, Station> stationEntry, SceneParam sceneParam) {
    // 获取当前时间点的进站人数信息
    Map<String, NumPeopEnStationApiInfo> numPeopleMap = numPeopEnStationApiInfoMap.get(now);
    if(now.equals("05:23:44")&&stationEntry.getValue().getName().equals("创新路")){
        System.out.println("ddddddd");
    }
    if (numPeopleMap == null && sceneParam.getSceneType().equals(SceneDataType.allDayHistoryData)) {
        return;
    }

    Station station = stationEntry.getValue();

    if(numPeopleMap.keySet().contains(station.getId())){
        int currentInCount = numPeopleMap.get(station.getId()).getStatValue();

//        int currentInCount = entry.getValue().getStatValue();//历史上，当前时间点，当前站进站的人
//           System.out.println(now);
//           System.out.println(station.getId());
//           System.out.println(currentInCount);

        currentInCount = stationChecker.checkAndAddPerson(now, station, currentInCount);

        long startTime_buildODRouteNumRatioMap = System.nanoTime();
        //
        Map<String, ODRouteNumRatio> odRouteNumRatioMap = buildODRouteNumRatioMap(station.getId());

        long endTime_buildODRouteNumRatioMap = System.nanoTime();
        long duration_buildODRouteNumRatioMap = endTime_buildODRouteNumRatioMap - startTime_buildODRouteNumRatioMap;
        System.out.println("程序运行时间: duration_buildODRouteNumRatioMap=" + duration_buildODRouteNumRatioMap  / 1_000_000+" 毫秒");

//           System.out.println("---------------");

        // 检查并添加进站人数

        if (currentInCount == 0) {
            return;
        }


        long startTime_loadHistoryPersonsToStation = System.nanoTime();
        // 加载历史人员数据
        loadHistoryPersonsToStation(station, currentInCount, odRouteNumRatioMap);

        long endTime_loadHistoryPersonsToStation = System.nanoTime();
        long duration_loadHistoryPersonsToStation = endTime_loadHistoryPersonsToStation - startTime_loadHistoryPersonsToStation;
        System.out.println("程序运行时间: duration_loadHistoryPersonsToStation=" + duration_loadHistoryPersonsToStation  / 1_000_000+" 毫秒");
    }


//   for(Map.Entry<String, NumPeopEnStationApiInfo> entry : numPeopleMap.entrySet()) {
//       if(entry.getKey().equals(station.getId())){
//
//
//       }
//   }

}




public List<ODRoutes> filterODRoutes( List<ODRoutes> odRoutesList) {

        return odRoutesList.stream()
                .map(odRoute -> {
                    // 过滤 RoutePath：仅保留所有 stationId 都存在于 stationMap 中的路径
                    List<RoutePath> filteredPaths = odRoute.getRoutePathList().stream()
                            .filter(routePath -> routePath.getRoutes().stream()
                                    .allMatch(station ->
                                            stationMap.containsKey(station.getStationId())
                                    )
                            )
                            .collect(Collectors.toList());

                    // 仅当过滤后的路径非空时才创建新 ODRoutes 对象
                    return !filteredPaths.isEmpty()
                            ? new ODRoutes(odRoute.getODName(), filteredPaths)
                            : null;
                })
                .filter(Objects::nonNull)  // 过滤掉空对象
                .collect(Collectors.toList());

//    List<ODRoutes> odRoutesListResult = new ArrayList<>();
//    for(int i=0;i<odRoutesList.size();i++){
//        List<RoutePath> routePathList = odRoutesList.get(i).getRoutePathList();
//        List<RoutePath> routePathList1=new ArrayList<>();
//        for(int m=0;m<routePathList.size();m++){
//            boolean isIn=true;
//            List<PressRouteStation> routes = routePathList.get(m).getRoutes();
//            for(int n=0;n<routes.size();n++){
//                String stationId = routes.get(n).getStationId();
//                System.out.println(stationId);
//                if(!stationMap.containsKey(stationId)){
//                    isIn=false;
//                }
//            }
//            if(isIn){
//                routePathList1.add(routePathList.get(m));
//            }
//
//        }
//
//        if(!routePathList1.isEmpty()){
//            ODRoutes odRoutes = new ODRoutes();
//            String odName = odRoutesList.get(i).getODName();
//            odRoutes.setRoutePathList(routePathList1);
//            odRoutes.setODName(odName);
//            odRoutesListResult.add(odRoutes);
//        }
//
//    }
//
//    return odRoutesListResult;
}
//    private  boolean containsStationId(ODRoutes odRoute) {
//
//        boolean b = odRoute.getRoutePathList().stream()
//                .anyMatch(routePath -> routePath.getRoutes().stream()
//                        .anyMatch(station -> lines.contains(stationMap.get(station.getStationId()).getLine())));
//        return b;
//
//
//    }



    /**
     * 构建ODRouteNumRatio映射
     *
     * @param currentInCount 当前进站人数
     * @return ODRouteNumRatio映射，包含各个OD路线的数量比例信息
     */
    private Map<String, ODRouteNumRatio> buildODRouteNumRatioMap(String stationId) {
        Map<String, ODRouteNumRatio> odRouteNumRatioMap = new HashMap<>();
        long startTime_getODRoutesList = System.nanoTime();//检查这个站是否有
        //一堆这个站点路径
        List<ODRoutes> odRoutesList1 = godAssistanter.getODRoutesList(stationId);

        long endTime_getODRoutesList= System.nanoTime();
        long duration_getODRoutesList = endTime_getODRoutesList - startTime_getODRoutesList;
        System.out.println("程序运行时间: getODRoutesList=" + duration_getODRoutesList  / 1_000_000+" 毫秒");
        long startTime_filterODRoutes = System.nanoTime();//检查这个站是否有

        List<ODRoutes> odRoutesList = filterODRoutes(odRoutesList1);

        long endTime_filterODRoutes= System.nanoTime();
        long duration_filterODRoutes = endTime_filterODRoutes - startTime_filterODRoutes;
        System.out.println("程序运行时间: filterODRoutes=" + duration_filterODRoutes  / 1_000_000+" 毫秒");


//        long startTime1 = System.nanoTime();//检查这个站是否有
//        long endTime1 = System.nanoTime();
//        long duration1 = endTime1 - startTime1;
//
//        // 输出运行时间 (以毫秒为单位)
//        System.out.println("程序运行时间: duration1=" + duration1 / 1_000_000 + " 毫秒");
        long startTime2_odRouteNumRatioMapList = System.nanoTime();


        odRouteNumRatioMap = odRoutesList.stream()
                .map(odRoutes -> {
                    String odName = odRoutes.getODName();
                    String modifiedString = insertUnderscore(odName); // 插入下划线
                    // 进行非空检查并获取概率信息
                    List<ODProbabilityApiInfo> odProbabilityApiInfos = odProbabilityApiInfoMap.get(modifiedString);

                    if (odProbabilityApiInfos != null && !modifiedString.isEmpty()) {
                        ODRouteNumRatio odRouteNumRatio = new ODRouteNumRatio();
                        odRouteNumRatio.setOdRoutes(odRoutes);
                        odRouteNumRatio.setSize(odProbabilityApiInfos.size());

                        odRouteNumRatio.setOdProbabilityApiInfoList(odProbabilityApiInfos);
                        return  new AbstractMap.SimpleEntry<>(odName, odRouteNumRatio); // 返回一个条目
                    }
                    return null; // 如果不满足条件，返回 null
                })
                .filter(entry -> entry != null) // 过滤掉 null 值
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); //
        long endTime2_odRouteNumRatioMapList = System.nanoTime();
        long duration2_odRouteNumRatioMapList = endTime2_odRouteNumRatioMapList - startTime2_odRouteNumRatioMapList;

        // 输出运行时间 (以毫秒为单位)
        System.out.println("程序运行时间:duration2_odRouteNumRatioMapList= " + duration2_odRouteNumRatioMapList / 1_000_000 + " 毫秒");





//        }


        return odRouteNumRatioMap;
    }


    /**
     * 在指定位置插入下划线
     *
     * @param str     原始字符串
     * @param
     * @return 修改后的字符串
     */
    public  String insertUnderscore(String str) {
        // 检查位置是否合法
        if (this.strPosition >= 0 && this.strPosition <= str.length()) {
            String beforeStr = str.substring(0, this.strPosition);
            String afterStr=str.substring(this.strPosition);

            String lineStr=afterStr.substring(0,this.strLinePosition);
            if(lineRooterMap.containsKey(lineStr)){
                return beforeStr + "_" +afterStr;
            }

            // 使用substring插入下划线
            return "";
        } else {
            throw new IllegalArgumentException("插入位置不合法");

        }
    }
    /**
     * 获取当前站点的进站人数
     *
     * @param numPeopleMap 当前时间的进站人数映射
     * @param stationId   站点ID
     * @return 进站人数，如果没有数据则返回0
     */
//    private int getCurrentInCount(Map<String, NumPeopEnStationApiInfo> numPeopleMap, String stationId) {
//        return Optional.ofNullable(numPeopleMap)
//                .map(map -> map.get(stationId))
//                .map(NumPeopEnStationApiInfo::getStatValue)
//                .orElse(0);
//    }

    /**
     * 根据路径分布情况，人数创建进站人员
     *
     * @param station             目标站点
     * @param personCount        要加载的人员数量
     * @param odRouteNumRatioMap OD路线数量比例映射
     */
    private void loadHistoryPersonsToStation(Station station, int personCount, Map<String, ODRouteNumRatio> odRouteNumRatioMap) {
        // 从人员创建器加载历史人员
//        List<Person> personList = station.getPersonCreater().loadHistoryPersons(personCount);

        personsCreater.setStationMap(stationMap);
        personsCreater.setTransferStationMap(transferStationMap);
        List<Person> personList = personsCreater.loadHistoryPersons(personCount, station, odRouteNumRatioMap);
        // 将人员列表转换为ID到人员对象的映射
        Map<String, Person> personMap = personList.stream()
                .collect(Collectors.toMap(Person::getId, person -> person));


        if(personMap.size()>0){
            // 更新站点的外部人员映射
            station.getOutsidePersonMap().putAll(personMap);
            // 调用人员创建器加载历史人员到站点
        }


    }
//    private void processStationData(String now, Map.Entry<String, Station> stationEntry, SceneParam sceneParam) {
//        // 获取当前时间点的进站人数信息
//        Map<String, NumPeopEnStationApiInfo> numPeopleMap = numPeopEnStationApiInfoMap.get(now);
//        if (numPeopleMap == null && sceneParam.getSceneType().equals(SceneDataType.allDayHistoryData)) {
//            return;
//        }
//        Station station = stationEntry.getValue();
//        int vsize = 0;
//        //添加进站人数
//        NumPeopEnStationApiInfo numPeopEnStationApiInfo = numPeopleMap.get(station.getId());
//        if (numPeopEnStationApiInfo != null) {
//            vsize = numPeopEnStationApiInfo.getStatValue();
//        }
//
//        Map<String, ODRouteNumRatio> ODRouteNumRatioMap = new HashMap<>();
//
//
//        for (Map.Entry<String, List<ODProbabilityApiInfo>> ODProbabilityApiInfoListEntry : odProbabilityApiInfoMap.entrySet()) {
//            ODRouteNumRatio odRouteNumRatio = new ODRouteNumRatio();
//            List<ODProbabilityApiInfo> ODProbabilityApiInfoList = ODProbabilityApiInfoListEntry.getValue();
//            String odId = ODProbabilityApiInfoListEntry.getKey();
//            if(odId.indexOf("_") != -1){
//                odId = odId.replace(String.valueOf("_"), "");
//            }
//            System.out.println(odId);
//            ODRoutes odRoutesObject = godAssistanter.getODRoutesObject(odId);
//            if(odRoutesObject!=null){
//                odRouteNumRatio.setOdRoutes(odRoutesObject);
//                odRouteNumRatio.setOdProbabilityApiInfoList(ODProbabilityApiInfoList);
//                odRouteNumRatio.setSize(ODProbabilityApiInfoList.size());
//                vsize = vsize + odRouteNumRatio.getSize();
//                ODRouteNumRatioMap.put(odId, odRouteNumRatio);
//            }
//
//        }
//        // 检查并添加进站人数
//        vsize = stationChecker.checkAndAddPerson(now, stationEntry.getValue(), vsize);
//        // 如果进站人数为0，直接返回
//        if (vsize == 0) {
//            return;
//        }
//
//        // 加载历史人员数据
//        List<Person> personList = station.getPersonCreater().loadHistoryPersons(vsize);
//        Map<String, Person> personMap = personList.stream()
//                .collect(Collectors.toMap(Person::getId, person -> person));
//
//        // 更新站点的外部人员映射
//        stationEntry.getValue().getOutsidePersonMap().putAll(personMap);
//
//        personsCreater.loadHistoryPersons(vsize, stationEntry.getValue(), ODRouteNumRatioMap);
//
//        // 加载历史人员到站点
////        loadHistoryPersons(vsize, odProbabilityApiInfosMap, stationEntry.getValue().getOutsidePersonMap());
//    }

    /** 
    * @description:
    *
    * @author: renzhg
    * @date: 2025/2/6 16:28
    **/
    public void calcullatePerson2Station(String now, Map<String, Station> lineStationMap) {
        SceneParam sceneParam = UnitCache.sceneParamMap.get(sceneCode);

        for (Map.Entry<String, Station> stationEntry : lineStationMap.entrySet()) {
            Station station = stationEntry.getValue();
            if (!station.isOpen()) {
                continue;
            }
            // 处理自定义数据加载
            if (sceneParam.getSceneType().equals(SceneDataType.customJson)) {
                // 自定义加载数据，暂未实现
                continue;
            }
            // 处理全天历史数据或时间段历史数据
            if (sceneParam.getSceneType().equals(SceneDataType.allDayHistoryData) ||
                    sceneParam.getSceneType().equals(SceneDataType.timePeriodHistoryData)) {

                processStationData(now, stationEntry, sceneParam);
            }

        }


    }

    public int calculatePersonCount(String routeRate, int infoSize) {
        double num = Double.parseDouble(routeRate) * 0.01 * infoSize;
        return (int) Math.floor(num);


    }

//    /**
//     * @description: 添加人数，当人数超过添加要求的人数时退出，根据概率值排序，然后添加人数
//     * @author: renzhg
//     * @date: 2024/11/17 18:23
//     **/
//    private void addPersonsWhenExceedingSize(int size,
//                                             Map<String, List<ODProbabilityApiInfo>> odProbabilityApiInfosMap,
//                                             Map<String, Person> outsidePersonMap) {
//        int count = 0;
//        //根据概率值排序
//        for (Map.Entry<String, List<ODProbabilityApiInfo>> entry : odProbabilityApiInfosMap.entrySet()) {
//            //根据概率值排序
//            Collections.sort(entry.getValue());
//            //当添加书人数超过要添加的人数时，返回
//            if (count >= size) {
//                return;
//            }
//
//            addPersonForRoute(entry.getValue().get(0).getRouteId(), outsidePersonMap);
//            count++;
//        }
//    }


    /**
     * @description: 该函数 loadHistoryPersons 用于根据传入的参数加载历史人员信息。具体功能如下：
     * 判断 odProbabilityApiInfosMap 的键数量是否超过 size：
     * 如果超过，则调用 addPersonsWhenExceedingSize 方法处理。
     * 否则，计算每个路由的信息量 infoSize，并调用 addPersonsBasedOnRouteRates 方法按比例添加人员。
     * 调用方法：
     * addPersonsWhenExceedingSize：处理超出大小的情况。
     * addPersonsBasedOnRouteRates：按比例分配人员
     * @author: renzhg
     * @date: 2024/11/17 18:21
     **/
//    public void loadHistoryPersons(int size,
//                                   Map<String, List<ODProbabilityApiInfo>> odProbabilityApiInfosMap,
//                                   Map<String, Person> outsidePersonMap) {
//        //路径概率机会数大于
//        if (odProbabilityApiInfosMap.keySet().size() > size) {
//            addPersonsWhenExceedingSize(size, odProbabilityApiInfosMap, outsidePersonMap);
//        } else {
//            int infoSize = size / odProbabilityApiInfosMap.size();
//            addPersonsBasedOnRouteRates(odProbabilityApiInfosMap, infoSize, outsidePersonMap);
//        }
//
//
//    }

//    /**
//     * @description: 这个地方有问题，添加人的时候发现路径为空的时候，就直接返回了没有添加，
//     * 所以这个人就没有添加进去，这个地方需要修改
//     * @author: renzhg
//     * @date: 2024/10/26 18:33
//     **/
//    private void addPersonForRoute(String routeId, Map<String, Person> outsidePersonMap) {
//
//        if (route2PersonPathMap.containsKey(routeId)) {
//            PersonPath personPath = route2PersonPathMap.get(routeId);
//            Person person = new Person(personPath);
//            person.setId(UUID.randomUUID().toString());
//            person.setInStationState();
//            outsidePersonMap.put(person.getId(), person);
//        }
//
//
//    }

//    private void addPersonsBasedOnRouteRates(Map<String, List<ODProbabilityApiInfo>> odProbabilityApiInfosMap,
//                                             Map<String, PersonPath> route2PersonPathMap,
//                                             int infoSize, Map<String, Person> outsidePersonMap) {
//        for (Map.Entry<String, List<ODProbabilityApiInfo>> entry : odProbabilityApiInfosMap.entrySet()) {
//            for (ODProbabilityApiInfo info : entry.getValue()) {
//                String routeId = info.getRouteId();
//                int result = calculatePersonCount(info.getRouteRate(), infoSize);
//                for (int j = 0; j < result; j++) {
//                    addPersonForRoute(routeId, outsidePersonMap);
//                }
//            }
//
//            // Add one more person for the first route in the current entry
//            addPersonForRoute(entry.getValue().get(0).getRouteId(), outsidePersonMap);
//        }
//    }


    /**
     * @description: 设定站点业务参数：1、进站里面人数的OD概率 2、每秒进站人数
     * @author: renzhg
     * @date: 2024/11/15 17:06
     **/
    public void initHisInputsParam(Map<String, Map<String, NumPeopEnStationApiInfo>> numPeopEnStationApiInfoMap) {
        this.lineRooterMap.forEach((k, v) -> {
            //设定站点业务参数：1、进站里面人数的OD概率 2、每秒进站人数
            v.setStationBizParam(numPeopEnStationApiInfoMap);

        });
    }


    @Override
    public LocalTime getCurrentTime() {
        return null;
    }

    @Override
    public void UpdateCurrentTime(LocalTime currentTime) {

    }

    @Override
    public void nextTime(String now, Integer step) {
        assignPerson2station(now);
    }
}
